/*
 * CloudBank Mobile Knowledge Sharing for Language Learners
 * Supported by the JISC Rapid Innovation Programme #jiscri
 *
 * Copyright (C) 2010 University of Brighton
 *
 * Licensed under the GNU General Public License v3 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.gnu.org/licenses/gpl.html
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
package uk.ac.brighton.itrg.cloudbank;

import android.app.Activity;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.text.util.Linkify;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

public class ActivityDetail extends Activity implements OnClickListener
{
	private static final String TAG = ActivityDetail.class.getSimpleName();
	
	private Item mItem = new Item();

	private TextView lblItem, lblDescription, lblTags;
	private ImageButton btnAudio, btnLink, btnFavs; 
	private ImageView imgFlag, imgDetail; 

	private Cursor mCursor;

	private MediaPlayer mPlayer;

	private ProgressDialog mProgress;
	private Handler mHandler, mFlagHandler; 

	private boolean flagUpdateContent;
	private boolean flagIsFavourite;

	// mww 06/2010 v.4  flag option
    private int mSelectedFlag;   

	
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
        Logger.log(TAG + ".onCreate()");
        try
        {
        	setContentView(R.layout.detail);

	        if (savedInstanceState != null) 
	        {
	        	String s = savedInstanceState.getString("mItem");
	        	Logger.log("SavedInstanceData", s);
	        	mItem.init(s);
	        }
	        else if(getIntent().hasExtra("Item._id"))  
        	{
	        	mItem._id = getIntent().getLongExtra("Item._id", mItem._id);
	        	Logger.log("getIntent().getLongExtra(Item._id)", mItem._id);
	        	flagUpdateContent = true;
        	}

        	// get UI handles
        	lblItem = (TextView) findViewById(R.id.lblItem);
        	lblDescription = (TextView) findViewById(R.id.lblDescription);
        	lblTags = (TextView) findViewById(R.id.lblTags);
        	imgFlag = (ImageView) findViewById(R.id.imgFlag);
        	imgDetail = (ImageView) findViewById(R.id.imgDetail);
        	btnAudio = (ImageButton) findViewById(R.id.btnAudio);
        	btnLink = (ImageButton) findViewById(R.id.btnLink);
        	btnFavs = (ImageButton) findViewById(R.id.btnFavs);
        	
	        // register listeners
        	lblItem.setOnClickListener(this);
        	lblDescription.setOnClickListener(this);
        	lblTags.setOnClickListener(this);
        	btnAudio.setOnClickListener(this);
        	btnLink.setOnClickListener(this);
        	btnFavs.setOnClickListener(this);

        	// don't need handles for these
        	findViewById(R.id.btnEdit).setOnClickListener(this);
        	findViewById(R.id.btnBack).setOnClickListener(this);
        }
        catch(Exception e)
        {
        	Logger.log(e);
        }
	}
	

	// ------------------------------------------
    // app becomes visible
	// ------------------------------------------
	public void onStart()
	{
		super.onStart();
        Logger.log(TAG + ".onStart()");
        
		if(flagUpdateContent) updateContent();
		else                  updateUI();       
	}

	
	// ------------------------------------------
    // asynchronously update item list and tag cloud
	// 1 - show ProgressDialog
	// 2 - set up handler to update UI with new data
	// 3 - start thread to retrieve new data
	// ------------------------------------------	
	private void updateContent()
	{
		mProgress = ProgressDialog.show(this, null, "loading, please wait...", true, false);

	    // Don't do UI stuff on on asynchronous thread... 
		mHandler = new Handler()
		{
	        public void handleMessage(Message msg) 
	        {
	        	mProgress.dismiss();
	        	
	        	if(DB.errorState())
	        	{
	            	new AlertDialog.Builder(ActivityDetail.this)
	                .setMessage(DB.getLastErrorMessage(ActivityDetail.this))
	                .setPositiveButton("OK", new DialogInterface.OnClickListener() 
	                {
	                        public void onClick(DialogInterface dialog, int whichButton) 
	                        {
	    		            	ActivityDetail.this.finish();
	                        } 
	                }).show();
	        	}
	        	else
	        	{
			    	updateUI();
	        	}
	        }
	    };

	    // Asynchronous: refresh Item cursor
		new Thread(new Runnable()
		{
			public void run()
			{
		    	mCursor = DB.getItem(mItem._id, ActivityDetail.this); 
		    	if(!DB.errorState())
		    	{
		    		mCursor.moveToFirst();
		    		mItem.flag = mCursor.getInt(1);
		    		mItem.item = mCursor.getString(2);
		    		mItem.description = mCursor.getString(3);
		    		mItem.link = mCursor.getString(4);
		    		mItem.image = mCursor.getString(5);
		    		mItem.audio = mCursor.getString(6);
		    		mItem.tags = mCursor.getString(7);

			    	if(mItem.image.length()>0)
			    	{
				        if(!Media.retrieveImageFromServer(mItem.image))
				        	mItem.image = "";
			    	}
					
			    	if(mItem.audio.length()>0)
			    	{
			    		if(!Media.retrieveAudioFromServer(mItem.audio))
			    			mItem.audio = "";
			    	}
		    	}
				mHandler.sendEmptyMessage(0);
			}
		}).start();
	}

	// ------------------------------------------
	// Update UI with current mItem values 
	// ------------------------------------------
    private void updateUI() 
    {
        lblItem.setText(truncate(mItem.item, 18, null));
        lblDescription.setText(truncate(mItem.description, 4*34, null));
        lblTags.setText(truncate(mItem.tags, 34, "Tags: "));
        
        if(mItem.flag>0)			imgFlag.setImageResource(R.drawable.flag_on);
        else						imgFlag.setImageResource(R.drawable.flag_off);
        
        if(mItem.image.length()>0)	imgDetail.setImageBitmap(Media.getTmpImage(288,216));
        else						imgDetail.setImageResource(R.drawable.detail_no_image);
        
    	if(mItem.audio.length()>0)	btnAudio.setImageResource(R.drawable.detail_audio);
    	else						btnAudio.setImageResource(R.drawable.detail_no_audio);

    	if(mItem.link.length()>0)	btnLink.setImageResource(R.drawable.detail_link);
    	else						btnLink.setImageResource(R.drawable.detail_no_link);
    	
    	flagIsFavourite = favIsBookmarked();
    	if(flagIsFavourite)			btnFavs.setImageResource(R.drawable.detail_fav_remove);
    	else						btnFavs.setImageResource(R.drawable.detail_fav_add);
    }
	
	// ------------------------------------------
	// Save away the original text, so we still have it 
    // if the activity needs to be killed while paused.
	// ------------------------------------------
    protected void onSaveInstanceState(Bundle outState) 
    {
    	Logger.log(TAG + ".onSaveInstanceState()");

    	String s = mItem.toString();    	
        outState.putString("mItem", s);

        Logger.log("mItem", s);
    }

	// ------------------------------------------
    // app becomes invisible
	// ------------------------------------------
	public void onStop()
	{
		super.onStop();
        Logger.log(TAG + ".onStop()");
        
        if(mPlayer != null)
        {
        	try 
        	{
        		mPlayer.stop();
        		mPlayer.release();
        	} 	
        	catch(Exception e)
        	{
        		Logger.log(e);
        	}
        	mPlayer = null;
        }
	}

	
	// ------------------------------------------
    // interface OnClickListener
	// ------------------------------------------
    public void onClick(View v) 
    {
        Logger.log(TAG + ".onClick()");
    	
    	switch(v.getId())
    	{
    	case R.id.lblItem: 

    		if(lblItem.getText().toString().endsWith(MORE))
    		{
	        	new AlertDialog.Builder(ActivityDetail.this)
	            .setMessage(mItem.item)
	            .setPositiveButton("Close", new DialogInterface.OnClickListener() 
	            {
	                    public void onClick(DialogInterface dialog, int whichButton) 
	                    {
			            	// do nothing
	                    } 
	            }).show();
    		}
        	break;
    		
    	case R.id.lblDescription: 

    		if(lblDescription.getText().toString().endsWith(MORE))
    		{
	        	new AlertDialog.Builder(ActivityDetail.this)
	            .setMessage(mItem.description)
	            .setPositiveButton("Close", new DialogInterface.OnClickListener() 
	            {
	                    public void onClick(DialogInterface dialog, int whichButton) 
	                    {
			            	// do nothing
	                    } 
	            }).show();
    		}
        	break;
    		
    	case R.id.lblTags: 
            
    		if(lblTags.getText().toString().endsWith(MORE))
    		{
	        	new AlertDialog.Builder(ActivityDetail.this)
	            .setMessage(mItem.tags)
	            .setPositiveButton("Close", new DialogInterface.OnClickListener() 
	            {
	                    public void onClick(DialogInterface dialog, int whichButton) 
	                    {
			            	// do nothing
	                    } 
	            }).show();
    		}
    		break;
    		
    	case R.id.btnAudio: 
            try 
            {
            	if(mItem.audio.length() > 0) 
            	{
            		
            		if (mPlayer == null)
            		{
            			mPlayer = MediaPlayer.create(this, Media.getTmpAudioUri());
            			mPlayer.setVolume(1.0f, 1.0f);
            		}

        			if(mPlayer.isPlaying())	mPlayer.stop();
        			else
        			{
                		Toast.makeText(this, "Playing audio...", Toast.LENGTH_SHORT).show();    
        				mPlayer.start();
        			}
            	}
            	else
            	{
    	        	new AlertDialog.Builder(ActivityDetail.this)
    	            .setMessage("No audio available!")
    	            .setPositiveButton("Close", new DialogInterface.OnClickListener() 
    	            {
    	                    public void onClick(DialogInterface dialog, int whichButton) 
    	                    {
    			            	// do nothing
    	                    } 
    	            }).show();
            	}            		
            } 
            catch (Exception e) 
            {
                Logger.log(e);
            }
    		break;
    		
    		
    	case R.id.btnLink: 
            try 
            {
            	if(mItem.link.length() > 0) 
            	{
            		Toast.makeText(this, "Starting browser...", Toast.LENGTH_SHORT).show();    
                	startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(mItem.link))); 
            	}
            	else
            	{
    	        	new AlertDialog.Builder(ActivityDetail.this)
    	            .setMessage("No link available!")
    	            .setPositiveButton("Close", new DialogInterface.OnClickListener() 
    	            {
    	                    public void onClick(DialogInterface dialog, int whichButton) 
    	                    {
    			            	// do nothing
    	                    } 
    	            }).show();
            	}            		
            } 
            catch (Exception e) 
            {
                Logger.log(e);
            }
    		break;
    		
    		
    		
    	case R.id.btnFavs: 
            try 
            {
            	String message = null;
            	if(flagIsFavourite) message = "Remove '" + mItem.item + "' from My Words list?";
            	else	 			message = "Add '" + mItem.item + "' to My Words list?";
            		
    	    	new AlertDialog.Builder(this)
    	        .setMessage(message)
    	        .setPositiveButton("Yes", new DialogInterface.OnClickListener() 
    	        {
    	                public void onClick(DialogInterface dialog, int whichButton) 
    	                {
    	            		if(flagIsFavourite) favRemove();
    	                	else				favAdd();
    	                } 
    	        })
    	        .setNegativeButton("No", new DialogInterface.OnClickListener() 
    	        {
    	                public void onClick(DialogInterface dialog, int whichButton) 
    	                {
    	                	// do nothing
    	                } 
    	        }).show();
            } 
            catch (Exception e) 
            {
                Logger.log(e);
            }
    		break;
    		
    		
    	case R.id.btnEdit: 
            try 
            {
            	Intent edit = new Intent(ActivityDetail.this, ActivityEdit.class);
    			edit.putExtra("mItem", mItem.toString());
    			startActivityForResult(edit, R.id.btnEdit);
            } 
            catch (Exception e) 
            {
                Logger.log(e);
            }
    		break;
    		

    	case R.id.btnBack: 
    		
       		setResult(RESULT_CANCELED);
    		finish();
    		break;
    	}
    }
    
    
    
    
	

	// ------------------------------------------
    // mww 06/2010 v.4 menu and preferences
    // create and listen to menu
	// ------------------------------------------
	public boolean onCreateOptionsMenu(Menu menu)
	{
		super.onCreateOptionsMenu(menu);
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.detail, menu);
		return true;
	}
	public boolean onOptionsItemSelected(MenuItem item)
	{
		switch(item.getItemId())
		{
		case R.id.mneFlag:
		     
        	 final String[] sFlags = getResources().getStringArray(R.array.menu_flag_reasons);
        	 mSelectedFlag = mItem.flag-1; // Flags are 1-based!!! (0 = not flag)
			 
		     AlertDialog.Builder builder = new AlertDialog.Builder(this);
		     builder.setTitle(R.string.menu_flag_title);
		     builder.setSingleChoiceItems(sFlags, -1, new DialogInterface.OnClickListener() 
		     {
		         public void onClick(DialogInterface dialog, int item) 
		         {
		        	 mSelectedFlag = item+1; // Flags are 1-based!!!
		         }
		     });
		     builder.setPositiveButton("Flag", new DialogInterface.OnClickListener() 
		     {
		            public void onClick(DialogInterface dialog, int whichButton) 
		            {
		            	flagItem();
	            	}
	         });
		     builder.setNegativeButton("Cancel", null);
		     builder.create().show();
			 
			 return true;

		case R.id.mneSettings:
			 startActivity(new Intent(this, ActivitySettings.class));
			 return true;

		case R.id.mneAbout:
			 final TextView message = new TextView(this);
		     final SpannableString s = new SpannableString(getText(R.string.about_text));
			 Linkify.addLinks(s, Linkify.WEB_URLS);
			 message.setText(s);
			 message.setMovementMethod(LinkMovementMethod.getInstance());

			 new AlertDialog.Builder(this)
			 .setTitle(R.string.about_title)
			 .setIcon(R.drawable.icon)
			 .setPositiveButton("OK", null)
			 .setView(message)
			 .show();
        	 
			 return true;

		case R.id.mneHelp:
			 startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(CB.getHelpPage(this)))); 
			 return true;
		}
		return false;
	}

	

	
    
    

	// ------------------------------------------
    // callback for sub-activities
	// ------------------------------------------
    protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    {
         super.onActivityResult(requestCode, resultCode, data);

         Logger.log(TAG + ".onActivityResult()");
         Logger.log("requestCode", requestCode);
         Logger.log("resultCode", resultCode);
         
         switch(requestCode)
         {
         
         case R.id.btnEdit:

        	 // do nothing 
        	 break;
         }
    }

    
    // -----------------------------------------------------
    // Handle MyWords ...  
    // -----------------------------------------------------
    private boolean favIsBookmarked()		
    {
    	boolean b = false;
    	Cursor c = DB.getLocalItem(mItem._id, this);
    	if(c != null) 
    	{
    		b = (c.getCount() > 0);
    	}
    	return b;
    }
    private void favAdd()		
    {
    	DB.putLocalItem(mItem, this);
    	flagIsFavourite = true;
    	btnFavs.setImageResource(R.drawable.detail_fav_remove);
        Toast.makeText(getApplicationContext(), "'" + mItem.item + "' has been added to your word list.", Toast.LENGTH_SHORT).show();
    }
    private void favRemove()
    {
    	DB.deleteLocalItem(mItem._id, this);
    	flagIsFavourite = false;
        btnFavs.setImageResource(R.drawable.detail_fav_add);    
        Toast.makeText(getApplicationContext(), "'" + mItem.item + "' has been removed from your word list.", Toast.LENGTH_SHORT).show();
    }


    // -----------------------------------------------------
    // Make sure that text is not longer than len including 
    // prefix. Truncate and add ... [more] if necessary.
    // -----------------------------------------------------
	private static final String ELLIPSIS = "...";
	private static final String MORE = " [more]";
    private static final Spannable truncate(String text, int len, String prefix)
    {
    	Spannable sp;
    	
    	String s = text;
    	if(prefix != null) s = prefix + text;
    	if(s.length() <= len) 
    	{
    		sp = new SpannableString(s);
    	}
    	else
    	{
    		int i = len - (ELLIPSIS + MORE).length();
    		sp = new SpannableString(s.substring(0, i) + ELLIPSIS + MORE);
    		
    		i = len - MORE.length() + 1;
    		sp.setSpan(new ForegroundColorSpan(0xFF3399FF), i, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    		sp.setSpan(new RelativeSizeSpan(0.75f), i, len, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
    	}
    	return sp;
    }
	
    
    

	
	// ------------------------------------------
    // update item list
	// ------------------------------------------	
	private void flagItem()
	{
		
		// notify user before we execute the server call
        Toast.makeText(getApplicationContext(), "Flagging this item...", Toast.LENGTH_SHORT).show();

        
		// ------------------------------------------
	    // asynchronous:
		// 1 - show ProgressDialog
		// 2 - set up handler to show result
		// ------------------------------------------	
		mFlagHandler = new Handler() // never update UI on asynchronous thread!
		{
	        public void handleMessage(Message msg) 
	        {
	        	String message;
	        	boolean flagUpdate = false;
	        	
	        	if(DB.errorState()) 
	        	{
		        	message = "An error occurred while flagging item \"" + mItem.item + "\": "
		        	        + "\n\n" + DB.getLastErrorMessage(ActivityDetail.this);
	        	}
	        	else
	        	{
	        		mItem.flag = mSelectedFlag + 1; // Flags are 1-based!!!
		        	message = "Item \"" + mItem.item + "\" has been flagged."
 	                        + "\n\nA message has been sent to the CloudBank administrator.";
	        		flagUpdate = true;
	        	}


            	new AlertDialog.Builder(ActivityDetail.this)
                .setMessage(message)
                .setPositiveButton("OK", null)
                .show();
            	
            	if(flagUpdate) updateUI();
	        }
	    };
	    
		new Thread(new Runnable() // asynchronously get remote cursor
		{
			public void run()
			{
                DB.flagItem(mItem._id, mSelectedFlag);
				mFlagHandler.sendEmptyMessage(0);
			}
		}).start();
	}


}
